Authentication by OAuth

Important: This mode of authentication is recommended for all interactive access to the API. Authentication by API key is available; this is disabled by default for all users, and access is granted specifically to each user account. API key authentication is recommended for running API-based automated tasks (see Authentication by API key).

When using OAuth-based authentication, API requests must be initiated with an authentication request to generate a bearer token (which is expressed as a JSON Web Token). The token is then included in the 'Authorization' header of every API request.

Authentication is based on an OAuth 2.0 process which can use several 'grant types'. This topic explains and shows examples for the 'Resource Owner password credentials grant' (which takes the form of a single API POST request, and is sometimes called 'silent authentication') and the 'implicit grant' (which involves a manual, interactive web browser action to 'login' with user credentials).

There are three types of PlanningSpace tenant user accounts: Local, SAML2, and Windows Active Directory (for details, see the PlanningSpace User Manual). SAML2 users are authenticated by an independent Identity Provider server, and this can only be handled using the implicit grant process.

For version 16.5 Update 13 and later: Authentication methods can be enabled or disabled for each tenant independently in IPS Manager (the default is all that all methods are enabled).

The disabling affects all interactive and API access for all user accounts of the specified type ('Local', 'SAML2', or 'Windows Active Directory'), and it includes API Key access.

If 'Local' accounts are disabled this will also disable the default 'Administrator' account for tenant administration.

Bearer Token lifetime

The bearer token has a set lifetime which applies to all users (including tenant Administrators) and all API requests. The lifetime is set for each tenant by the IPS Administrator, either using the 'Token lifetime' setting in the IPS Manager user interface, or using the Admin API ('/api/TenantSettingsCommands/SetTokenLifetime'). Note: it cannot be modified by a tenant Administrator.

For reasons of protecting the PlanningSpace service from unauthorized use, the token lifetime is set relatively short: 15 minutes, i.e. 900 seconds, is the default. A new authentication request must be made to replace an expired token. When a token is successfully generated, the response JSON also contains a value 'expires_in' which is the token lifetime in seconds. The minimum lifetime setting is 5 minutes, and the maximum lifetime is 1440 minutes.

Resource Owner grant

Authentication in this case requires a single POST request of the form:

POST /identity/connect/token
Content-Type: "application/x-www-form-urlencoded"
"grant_type=password&username={USER}&password={PASSWORD}&scope=planningspace&client_id={TENANTNAME}+resource_owner&client_secret="

The request is sent to a PlanningSpace IPS Server address (not tenant address), e.g. 'https://ipsserver.mycompany.com'.

There are three values to insert: {USER} is a PlanningSpace tenant username, {PASSWORD} is the explicit password text, and {TENANTNAME} is the name of a PlanningSpace tenant.

A successful response is of type "application/json" with the form:

{'access_token': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjA3RDM3QkQwOEQ3MzhEQzZCOTdEMjk2MThEMzg3MDg1ODMwRTIxQTgiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJCOU43ME...',
'expires_in': 900,
'token_type': 'Bearer'}

The access token is a JSON Web Token (JWT), which is more than 1000 characters long - most of which have been omitted from the above example output. The JWT contains encoded (but not encrypted!) information about the server which granted the token, the username of the account used, the time the token was issued, and the token's expiry time. It's not necessary to know any of this information to use the token (but when you use the token you should never send it through a non-encrypted HTTP connection since anyone intercepting your API calls could immediately extract its information).

Implicit grant

Authentication in this case involves invoking a web browser process to connect to the 'login' interface of the IPS Server, and extracting the bearer token which will be sent if the login is successful.

The PowerShell example code below shows how the implicit grant flow can be implemented as a program.

You can manually test the flow using a web browser. For example, in PowerShell set up some variables as follows, inserting actual values for your PlanningSpace server address and tenant name:

Copy
$serverUrl = 'https://ipsserver.mycompany.com'
$tenantName = 'tenant1'

Now copy-and-paste this input:

Copy
"$serverUrl/identity/connect/authorize?response_type=token&state=NONE&client_id=$tenantName%20web&scope=planningspace&redirect_uri=$serverUrl/$tenantName/loginCallback.html"

The output of this line will look like this, with the variable values substituted:

https://ipsserver.mycompany.com/identity/connect/authorize?response_type=token&state=NONE&client_id=tenant1%20web&scope=planningspace&redirect_uri=https://ipsserver.mycompany.com/tenant1/loginCallback.html

Copy this output line exactly (with no linebreaks) and paste it into the URL input field of a web browser. All being well you will see the PlanningSpace login dialog. Login with your user account as you would usually do for logging directly into PlanningSpace (website or client application), and if successful the API access token will be contained in the 'return URL' that appears in the browser's URL field. For example:

https://ipsserver.mycompany.com/tenant1/loginCallback.html#access_token=eyJhbGc...ByyLBhDg7fg&token_type=Bearer&expires_in=900&scope=planningspace&state=NONE

The access token string (abbreviated above) could now be used for API requests, in the same way as for the Resource Owner grant process. See the example code below for a practical implementation of the authentication process in PowerShell.

Important: The PlanningSpace server maintains a login 'session' for a duration that is equal to the 'token lifetime'. If you connect to the authorization service again within this time, from the same client location, you will get a new access token returned without needing to enter your login credentials. If you add 'prompt=login' as a request parameter this will force the server to request your login credentials.

The 'state' parameter is a required parameter for the authorization request URL. It should be set to a random alphanumeric string, and your API programs should check that the 'return URL' contains the same state value, as a check against cross-site request forgery (CSRF). If this check is not being done, you can set 'state' to any value and ignore the returned value.

Code sample (PowerShell): Resource Owner grant

It is simple to use Windows PowerShell to do ad hoc API requests or to write scripts. The 'Invoke-RestMethod' command is available in all versions of PowerShell.

First, set variables for the server and user details:

Copy
$serverUrl = 'https://ipsserver.mycompany.com'
$tenantName = 'tenant1'
$user = 'someone'
$pass = 'SECRET'

And then execute the authentication request:

Copy
$authResponse = Invoke-RestMethod -Method Post -Uri "$serverUrl/identity/connect/token" -Body "grant_type=password&username=$user&password=$pass&scope=planningspace&client_id=$tenantName+resource_owner&client_secret="

If successful, the contents of '$authResponse' will contain the access token. You can check this using the input:

Copy
$authResponse | Get-Member -MemberType NoteProperty | select -Property Name, Definition

Example output:

 Name         Definition
----         ----------
access_token string access_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjA3RDM3QkQwOEQ3MzhEQzZCOTdEMj...
expires_in   int expires_in=900
token_type   string token_type=Bearer

The access token can be extracted like this:

Copy
$authResponse.access_token

Now use this to make an API request. For example:

Copy
$tenantUrl = "$serverUrl/$tenantName"
Invoke-RestMethod -Uri "$tenantUrl/PlanningSpaceEconomics/data/v1/Currencies" -header @{'Authorization' = 'Bearer ' + $authResponse.access_token}

The 'Authorization' header simply consists of a string which is the access token, pre-pended by 'Bearer ' (the space character after 'Bearer' is required).

Code sample (PowerShell): Implicit grant

The following function implements the implicit grant flow using a PowerShell built-in module to launch a browser object.

Copy the whole block of code, and save it as a 'ps1' script file, for example 'Get-PSAuthToken.ps1'.

Copy
# PlanningSpace 16.5 Web API
# Function to invoke Implicit Flow interactive login via a browser

Function Get-PSAuthToken ($tenantUrl)
{
    Add-Type -AssemblyName System.Windows.Forms

    $tenantUrl = $tenantUrl.Trim("/") + "/"
    $url = [System.Uri]$tenantUrl
    $script:returnUrl = ""

    $authUrl = "{0}/identity/connect/authorize?response_type=token&state=NONE&client_id={1}%20web&scope=planningspace&redirect_uri={2}loginCallback.html" `
        -f $url.GetLeftPart([System.UriPartial]::Authority), $url.Segments[1].Trim("/"), [System.Uri]::EscapeUriString($tenantUrl)

    $popupForm = New-Object -TypeName System.Windows.Forms.Form -Property @{Width=500;Height=700}
    $browser  = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{Url=$authUrl}
    $completedHandler  = {
            $script:returnUrl = $browser.Url.AbsoluteUri
            if ($script:returnUrl -match "error=[^&]*|access_token=[^&]*")
            {
                $popupForm.Close() 
            }
    }
    
    $browser.Add_DocumentCompleted($completedHandler)
    $popupForm.Controls.Add($browser)
    $browser.Dock = [System.Windows.Forms.DockStyle]::Fill

    $popupForm.Add_Shown({$popupForm.Activate()})
    $popupForm.ShowDialog() | Out-Null

    [RegEx]::Match(([System.Uri]$script:returnUrl).Fragment, "(access_token=)(.*?)(&)").Groups[2].Value
}

Load the new function into your current PowerShell (note the dot character at the start is essential):

Copy
. .\Get-PSAuthToken.ps1

And run it with a tenant URL as the input:

Copy
$tenantUrl = 'https://ipsserver.mycompany.com/tenant1'
$token = Get-PSAuthToken($tenantUrl)

The output of the function, saved in '$token', should be an access token that can now be used for API requests, for example:

Copy
Invoke-RestMethod -Uri "$tenantUrl/PlanningSpaceEconomics/data/v1/Currencies" -header @{'Authorization' = 'Bearer ' + $token}